use crate::data::{ANode, Node};
use eframe::egui::{Button, Color32, Frame, Response, Sense, Ui, Vec2, Widget};
use std::sync::Arc;

pub struct NodeItemUI {
    node: ANode,
    curr_id: u32,
    layer: f32,
}

impl NodeItemUI {
    pub fn new(node: ANode, curr_id: u32, layer: f32) -> NodeItemUI {
        Self{
            node,
            curr_id,
            layer,
        }
    }

    fn get_expand_text(&self) -> String {
        let expand_text = if let Ok(node) = self.node.try_lock() {
            if node.is_expand { "▶" }
            else { "▼" }
        } else { "▶" };
        expand_text.to_string()
    }

    fn draw_expand_btn(&self, ui: &mut Ui) {
        let old_button_padding = ui.spacing().button_padding;
        let old_item_spacing = ui.spacing().item_spacing;
        ui.spacing_mut().button_padding = Vec2::ZERO;
        ui.spacing_mut().item_spacing = Vec2::X * 3.;
        let button = Button::new(self.get_expand_text())
            .fill(Color32::TRANSPARENT)
            .frame(false);
        if button.ui(ui).clicked() {
            if let Ok(mut node) = self.node.try_lock() {
                node.is_expand = !node.is_expand;
            };
        }
        ui.spacing_mut().button_padding = old_button_padding;
        ui.spacing_mut().item_spacing = old_item_spacing;
    }

    fn get_item_title(&self) -> String {
        if let Ok(node) = self.node.try_lock() {
            node.title.value.clone()
        } else { "".to_string() }
    }

    fn draw_item_btn(&self, ui: &mut Ui) -> Response {
        let old_button_padding = ui.spacing().button_padding;
        let old_item_spacing = ui.spacing().item_spacing;
        ui.spacing_mut().item_spacing = Vec2::X * 5.;
        ui.spacing_mut().button_padding = Vec2::ZERO;
        let response = Button::new(self.get_item_title())
            .fill(Color32::TRANSPARENT)
            .frame(false).ui(ui);
        ui.spacing_mut().button_padding = old_button_padding;
        ui.spacing_mut().item_spacing = old_item_spacing;
        response
    }

    fn draw_relate_btn(&self, ui: &mut Ui) {
        if let Ok(node) = self.node.try_lock() {
            if let Some(ref relate) = node.relate {
                self.do_draw_relate_btn(ui, relate);
            } else if let Some(ref relate) = node.relate_parent {
                if let Some(ref relate) = relate.upgrade() {
                    self.do_draw_relate_btn(ui, relate);
                }
            }
        }
    }

    fn do_draw_relate_btn(&self, ui: &mut Ui, relate: &ANode) {
        let button = Button::new("=>")
            .corner_radius(10.)
            .fill(Color32::GREEN)
            .frame(false);
        if button.ui(ui).clicked() {
            Node::set_current_node(ui.ctx(), Arc::clone(relate));
            Node::set_list_root_node(ui.ctx(), Arc::clone(relate));
        }
    }
}

impl Widget for NodeItemUI {
    fn ui(self, ui: &mut Ui) -> Response {
        let color = if let Ok(node) = self.node.try_lock() {
            if node.id == self.curr_id { Color32::LIGHT_GRAY }
            else { Color32::TRANSPARENT }
        } else { Color32::TRANSPARENT };

        Frame::new().fill(color).show(ui, |ui| {
            // 绘制 |▶|item_title|➽| 组合按钮
            ui.horizontal(|ui| {
                let mut vec = vec![];
                // 绘制空白缩进
                let response = ui.allocate_response(
                    Vec2::new(self.layer * 20., ui.available_height()),
                    Sense::click()
                );
                vec.push(response);

                // 绘制折叠按钮
                self.draw_expand_btn(ui);
                // 绘制item
                let response = self.draw_item_btn(ui);
                vec.push(response);

                // 绘制关联按钮
                self.draw_relate_btn(ui);

                // 绘制剩下空白
                let response = ui.allocate_response(
                    Vec2::new(ui.available_width(), ui.available_height()),
                    Sense::click()
                );
                vec.push(response);

                for x in vec {
                    if x.clicked() {
                        Node::set_current_node(ui.ctx(), Arc::clone(&self.node));
                    }
                }
            }).response
        }).response
    }
}
